package routers

import (
	"encoding/json"
	"fly/global"
	"fly/helper"
	"fly/models"
	"fly/req"
	"fly/resp"
	"fly/schema"
	"fly/service"
	"github.com/beego/beego/v2/core/logs"
	"github.com/beego/beego/v2/server/web/context"
	"github.com/duke-git/lancet/v2/condition"
	"github.com/duke-git/lancet/v2/convertor"
	ua "github.com/mileusna/useragent"
	"regexp"
	"slices"
	"strconv"
	"strings"
	"time"
)

func AddRequestMsgId(ctx *context.Context) {
	traceID := ctx.Request.Header.Get(schema.TrackKey)
	if traceID == "" {
		traceID = NewTraceID()
	}
	ctx.Request.Header.Set(schema.TrackKey, traceID)
	ctx.Request.Header.Set(schema.TrackTime, strconv.FormatInt(helper.UnixMilli(time.Now()), 10))
}

func ApiLogPrinter(ctx *context.Context) {
	url := ctx.Request.RequestURI
	params := string(ctx.Input.RequestBody)
	outputBytes, _ := json.Marshal(ctx.Input.Data()["json"])
	divider := " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
	topDivider := "┌" + divider
	middleDivider := "├" + divider
	bottomDivider := "└" + divider
	outputStr := "\n" + topDivider + "\n│ 请求地址:" + url + "\n" + middleDivider + "\n│ 请求参数:" + string(params) + "\n│ 返回数据:" + string(outputBytes) + "\n" + bottomDivider
	logs.Info(outputStr)
}

func ApiLogRecord(ctx *context.Context) {
	url := ctx.Request.RequestURI
	params := string(ctx.Input.RequestBody)
	now := time.Now()
	outputBytes, _ := json.Marshal(ctx.Input.Data()["json"])
	if isLogin := strings.Contains(url, "sys/user/login"); isLogin {
		loginReq := req.LoginReq{}
		err := ctx.BindJSON(&loginReq)
		if err != nil {
			return
		}
		uAgent := ua.Parse(ctx.Input.UserAgent())
		_, _ = models.AddSysLogAdminLogin(&models.SysLogAdminLogin{
			UserName:  loginReq.Username,
			Ipaddr:    ctx.Input.IP(),
			Browser:   uAgent.Name,
			Os:        uAgent.OS,
			Status:    ctx.Output.Status,
			LoginTime: &now,
		})
	} else {
		userId := ctx.Input.Param(schema.KeyAuthTokenUserId)
		trackTime, _ := convertor.ToInt(ctx.Request.Header.Get(schema.TrackTime))
		costTime := int64(0)
		if trackTime > 0 {
			costTime = helper.UnixMilli(time.Now()) - trackTime
		}
		id, _ := convertor.ToInt(userId)
		var sysUser service.SysUserService
		var sysDept service.SysDeptService
		userName, _ := sysUser.GetUserRealNameById(id)
		deptName, _ := sysDept.GetSimpleDeptNameById(id)
		_, _ = models.AddSysLogAdmin(&models.SysLogAdmin{
			BusinessType:  condition.TernaryOperator(ctx.Input.IsDelete(), 3, 0),
			Method:        ctx.Input.Method(),
			RequestMethod: ctx.Input.RunMethod,
			OperatorType:  1,
			OperName:      userName,
			DeptName:      deptName,
			OperUrl:       url,
			OperIp:        ctx.Input.IP(),
			OperParam:     params,
			JsonResult:    string(outputBytes),
			Status:        ctx.Output.Status,
			OperTime:      &now,
			CostTime:      costTime,
			OperUserId:    id,
		})
	}
}

func CheckAuth(ctx *context.Context) bool {
	token := ctx.Request.Header.Get(schema.TokenKey)
	url := ctx.Request.RequestURI
	isMatch := slices.ContainsFunc(AuthWhiteList, func(s string) bool {
		m, _ := regexp.MatchString(s, url)
		return m
	})
	if !isMatch {
		if len(token) == 0 {
			logs.Error("request>> %s no auth", url)
			_ = ctx.JSONResp(resp.StatusResult{
				Code:    401,
				Status:  schema.ErrorStatus,
				TraceId: ctx.Request.Header.Get(schema.TrackKey),
				Message: "权限异常",
			})
			return false
		} else {
			userId, err := global.JwtAuth.ParseUserID(ctx.Request.Context(), token)
			if err != nil {
				_ = ctx.JSONResp(resp.StatusResult{
					Code:    401,
					Status:  schema.ErrorStatus,
					TraceId: ctx.Request.Header.Get(schema.TrackKey),
					Message: "Token异常",
				})
				return false
			}
			ctx.Input.SetParam(schema.KeyAuthTokenUserId, userId)
		}
	}
	return true
}
